package com.lit.server;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;

public class ServerInstance implements Runnable 
{
	//String signal to stop the server
	private final String STOP_MESSAGE = "STP:";
	//Delimiter between username and password for login stuff
	private final char DELIM = ':';
	
	//Available users to login to
	private HashMap<String, String> users;
	//Users currently connected
	private HashMap<String, InetAddress> connectedusers;
	//Arbitrary name of the server instance
	String name;
	//Temporary packet for connection requests
	DatagramSocket incoming, outgoing;
	//Since port is grabbed based on whatever is available, need to know
	int port;
	
	boolean auth = true;
	
	public ServerInstance(String name, HashMap<String, String> users, int port)
	{	
				try 
				{
					if(port>-1 || port>65534)
					incoming = new DatagramSocket(port);
					else
					incoming = new DatagramSocket(0);
					
					incoming.setSoTimeout(0);
				} 
				catch (IOException e) 
				{
					System.out.println("Cannot bind socket, exiting.");
					e.printStackTrace();
				}
				
		this.port = incoming.getLocalPort();
		
		if(users.isEmpty() || users == null)
		{
			//this.users = new HashMap<String, String>(1);
			this.auth = false;
			//this.users.put("Guest", "Guest"); 
		}
		else
			this.users = users;
		
		if(name != null && !name.isEmpty())
			this.name = name;
		else
			this.name = "Server Instance " + port;

	}
	
	@Override
	public void run() 
	{
		boolean run = true;
		
		while(run)
		{
			DatagramPacket userinfo = new DatagramPacket(new byte[27], 27);
			try 
			{
				incoming.receive(userinfo);
				String[] parsedUI = new String[2];
				if((parsedUI = parseUserPacket(userinfo.getData())) != null)
				{
					if(!parsedUI[0].equals(STOP_MESSAGE) && !userinfo.getAddress().equals(incoming.getLocalAddress()))
					{
						if(auth)
						{
							if(users.get(parsedUI[0]).equals(parsedUI[1]))
								this.connectedusers.put(parsedUI[0], userinfo.getAddress());
							else
							{
								System.out.println("Attempted login failed. User: " 
										+ parsedUI[0] + " Attempted Password: " + parsedUI[1]);
							}
						}
						else
							this.connectedusers.put(parsedUI[0], userinfo.getAddress());
					}
					else
					run = false;
				}

			} 
			catch (IOException e) 
			{
				System.out.println("Error listening on bound port: ");
				e.printStackTrace();
			}
		}
		
		return;
	}
	
	
	private String[] parseUserPacket(byte[] raw)
	{
		String[] returnval = null;
		String rawString = new String(raw);
		rawString = rawString.trim();
		
		
		int delimindex = 0;
		
		if((delimindex = rawString.indexOf(DELIM)) != -1)
		{
			returnval = new String[2];
			
			if(!rawString.equals(STOP_MESSAGE))
			{
				if(auth)
				{
					returnval[0] = rawString.substring(0, delimindex);
					returnval[1] = rawString.substring(delimindex+1);
				}
				else
					returnval[0] = rawString.substring(0, delimindex);
			}
			else
				returnval[0]=STOP_MESSAGE;
		}
		
		return returnval;
	}
	
	public void stop()
	{
		try {
			DatagramPacket stop = new DatagramPacket(STOP_MESSAGE.getBytes(), 27);
			outgoing = new DatagramSocket();
			outgoing.connect(InetAddress.getByName("localhost"), this.port);
			outgoing.send(stop);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//stop.
		
	}
	
	
}